package com.ecoolex.ying.space.core.manager;

import com.ecoolex.framework.common.pojo.Page;
import com.ecoolex.framework.common.pojo.Pagination;
import com.ecoolex.framework.common.pojo.Sorting;
import com.ecoolex.framework.common.pojo.Sortings;
import com.ecoolex.framework.common.util.Check;
import com.ecoolex.ying.space.core.dao.UserWorksCommentDAO;
import com.ecoolex.ying.space.entity.UserWorksComment;
import com.ecoolex.ying.space.entity.UserWorksComment.Column;
import com.ecoolex.ying.space.entity.UserWorksCommentExample;
import com.ecoolex.ying.space.entity.UserWorksCommentExample.Criteria;
import com.ecoolex.ying.space.entity.UserWorksCommentReadState;
import com.ecoolex.ying.space.enums.UserWorksCommentAuditStatus;

import java.time.Instant;
import java.util.Date;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;


@Service
public class UserWorksCommentManager {

    @Autowired
    private UserWorksCommentDAO dao;

    @Autowired
    private UserWorksStatisticalManager userWorksStatisticalManager;

    @Autowired
    private UserWorksCommentReadStateManager userWorksCommentReadStateManager;

    @Autowired
    private UserWorksAuditManager userWorksAuditManager;

    /**
     * 添加内容评论
     * 
     * @param record
     * @param createUser
     * @return
     */
    @Transactional
    public UserWorksComment addUserWorksComment(UserWorksComment record, String createUser) {
        record.setPraseCount(0);
        record.setCommentCount(0);
        record.setBeCommentUserId(record.getWorksUserId());
        record.setLastCommentId(0);
        record.setReplyId(0);
        record.setAuditRecordId(0);
        record.setAuditStatus(UserWorksCommentAuditStatus.WAITAUDIT.real());
        record.setDeleted(UserWorksComment.NOT_DELETED);
        record.setCreateUser(createUser);
        record.setCreateTime(Date.from(Instant.now()));
        record.setUpdateUser(createUser);
        record.setUpdateTime(Date.from(Instant.now()));
        dao.insert(record);
        // 审核
        userWorksAuditManager.applyComment(record);
        // 记录作品评论数
        userWorksStatisticalManager.commentCount(record.getWorksId(), createUser);
        return record;
    }

    /**
     * 添加评论回复
     * 
     * @param record
     * @param createUser
     * @return
     */
    @Transactional
    public UserWorksComment addUserWorksReply(UserWorksComment record, String createUser) {
        // 根据传入的上层评论id查询上层评论对象
        UserWorksComment userWorksComment = getById(record.getLastCommentId());
        // 回复的评论是第一层评论
        if (userWorksComment.getLastCommentId() == 0) {
            record.setLastCommentId(userWorksComment.getCommentId());
            record.setReplyId(0);
        } else {
            record.setLastCommentId(userWorksComment.getLastCommentId());
            record.setReplyId(userWorksComment.getCommentId());
        }
        record.setBeCommentUserId(userWorksComment.getCommentUserId());
        record.setPraseCount(0);
        record.setCommentCount(0);
        record.setAuditRecordId(0);
        record.setAuditStatus(UserWorksCommentAuditStatus.WAITAUDIT.real());
        record.setDeleted(UserWorksComment.NOT_DELETED);
        record.setCreateUser(createUser);
        record.setCreateTime(Date.from(Instant.now()));
        record.setUpdateUser(createUser);
        record.setUpdateTime(Date.from(Instant.now()));
        dao.insert(record);

        // 审核
        userWorksAuditManager.applyComment(record);
        // 评论回复计数
        commentCount(record.getLastCommentId(), createUser);

        return record;
    }

    public void resetAuditStatus(UserWorksComment record, UserWorksCommentAuditStatus auditStatus, boolean isUpdateContent, String updateUser) {
        record.setAuditStatus(auditStatus.real());
        record.setUpdateUser(updateUser);
        record.setUpdateTime(Date.from(Instant.now()));
        if (isUpdateContent) {
            dao.updateByPrimaryKeySelective(record,
                Column.content,
                Column.image,
                Column.auditRecordId,
                Column.auditStatus,
                Column.updateUser,
                Column.updateTime);
        } else {
            dao.updateByPrimaryKeySelective(record, Column.auditRecordId, Column.auditStatus, Column.updateUser, Column.updateTime);
        }

    }

    /**
     * 点赞评论统计
     * 
     * @param record
     * @param updateUser
     * @return
     */
    public boolean praseComment(Integer commentId, String updateUser) {
        return dao.praseComment(commentId, updateUser) == 1;
    }

    /**
     * 取消点赞评论统计
     * 
     * @param commentId
     * @param updateUser
     */
    public void cancelPraseComment(Integer commentId, String updateUser) {
        dao.cancelPraseComment(commentId, updateUser);
    }

    /**
     * 评论计数
     * 
     * @param id
     * @param updateUser
     */
    public void commentCount(Integer commentId, String updateUser) {
        dao.commentCount(commentId, updateUser);
    }

    @Transactional
    public void delete(UserWorksComment record, String updateUser) {
        record.setDeleted(UserWorksComment.IS_DELETED);
        record.setUpdateUser(updateUser);
        record.setUpdateTime(Date.from(Instant.now()));
        dao.updateByPrimaryKeySelective(record, Column.deleted, Column.updateUser, Column.updateTime);
        // 删除评论作品计数
        userWorksStatisticalManager.delCommentCount(record.getWorksId(), updateUser);
    }

    public UserWorksComment getByIdForH5(Integer commentId) {
        UserWorksCommentExample example = new UserWorksCommentExample();
        Criteria criteria = example.createCriteria();
        criteria.andCommentIdEqualTo(commentId).andAuditStatusEqualTo(
            UserWorksCommentAuditStatus.PASS.real()).andDeletedEqualTo(UserWorksComment.NOT_DELETED);
        return dao.selectOneByExample(example);
    }

    public Pagination<UserWorksComment> queryCommentForH5(Date now, Integer worksId, Sorting[] sorts, Page page) {
        UserWorksCommentExample example = new UserWorksCommentExample();
        Criteria criteria = example.createCriteria();
        criteria.andWorksIdEqualTo(worksId).andLastCommentIdEqualTo(0).andCreateTimeLessThanOrEqualTo(
            now).andAuditStatusEqualTo(UserWorksCommentAuditStatus.PASS.real()).andDeletedEqualTo(
                UserWorksComment.NOT_DELETED);
        example.orderBy(Sortings.builder(sorts).verify(Column::valueOf).toSql());
        example.setOffset(page.getFirstIndex());
        example.setRows(page.getPageSize());

        return Pagination.create(page, dao.countByExample(example), () -> dao.selectByExample(example));
    }

    public Pagination<UserWorksComment> queryReplyForH5(Date now, Integer lastCommentId, Sorting[] sorts, Page page) {
        UserWorksCommentExample example = new UserWorksCommentExample();
        Criteria criteria = example.createCriteria();
        criteria.andLastCommentIdEqualTo(lastCommentId).andCreateTimeLessThanOrEqualTo(now).andAuditStatusEqualTo(
            UserWorksCommentAuditStatus.PASS.real()).andDeletedEqualTo(UserWorksComment.NOT_DELETED);
        example.orderBy(Sortings.builder(sorts).verify(Column::valueOf).toSql());
        example.setOffset(page.getFirstIndex());
        example.setRows(page.getPageSize());

        return Pagination.create(page, dao.countByExample(example), () -> dao.selectByExample(example));
    }

    public Pagination<UserWorksComment> queryByCommentUserIdForH5(Integer commentUserId, Sorting[] sorts, Page page) {
        UserWorksCommentExample example = new UserWorksCommentExample();
        Criteria criteria = example.createCriteria();
        criteria.andCommentUserIdEqualTo(commentUserId).andAuditStatusEqualTo(
            UserWorksCommentAuditStatus.PASS.real()).andDeletedEqualTo(UserWorksComment.NOT_DELETED);
        example.orderBy(Sortings.builder(sorts).verify(Column::valueOf).toSql());
        example.setOffset(page.getFirstIndex());
        example.setRows(page.getPageSize());

        return Pagination.create(page, dao.countByExample(example), () -> dao.selectByExample(example));
    }

    public Pagination<UserWorksComment> queryByBeCommentUserIdForH5(Date now, Integer beCommentUserId, Sorting[] sorts, Page page) {
        UserWorksCommentExample example = new UserWorksCommentExample();
        Criteria criteria = example.createCriteria();
        criteria.andBeCommentUserIdEqualTo(beCommentUserId).andCreateTimeLessThanOrEqualTo(now).andAuditStatusEqualTo(
            UserWorksCommentAuditStatus.PASS.real()).andDeletedEqualTo(UserWorksComment.NOT_DELETED);
        example.orderBy(Sortings.builder(sorts).verify(Column::valueOf).toSql());
        example.setOffset(page.getFirstIndex());
        example.setRows(page.getPageSize());

        return Pagination.create(page, dao.countByExample(example), () -> dao.selectByExample(example));
    }

    public long unreadReceivedCommentCount(Integer userId) {
        UserWorksCommentExample example = new UserWorksCommentExample();
        Criteria criteria = example.createCriteria();
        // 获取用户最新的评论读取状态
        UserWorksCommentReadState readState = userWorksCommentReadStateManager.getById(userId);
        if (Check.notNull(readState)) {
            Date newReadTime = readState.getNewReadTime();
            criteria.andBeCommentUserIdEqualTo(userId).andCommentUserIdNotEqualTo(userId)
            .andAuditStatusEqualTo(UserWorksCommentAuditStatus.PASS.real()).andCreateTimeGreaterThan(newReadTime)
            .andDeletedEqualTo(UserWorksComment.NOT_DELETED);
        } else {
            criteria.andBeCommentUserIdEqualTo(userId).andCommentUserIdNotEqualTo(userId)
            .andAuditStatusEqualTo(UserWorksCommentAuditStatus.PASS.real()).andDeletedEqualTo(UserWorksComment.NOT_DELETED);
        }
        return dao.countByExample(example);
    }

    public UserWorksComment getById(Integer commentId) {
        return dao.selectByPrimaryKeyWithLogicalDelete(commentId, UserWorksComment.NOT_DELETED);
    }

    public Pagination<UserWorksComment> queryByOpus(String title, Sorting[] sorts, Page page) {

        return Pagination.create(page,
            dao.countByOpus(title),
            () -> dao.queryByOpus(title, Sortings.builder(sorts).toSql(), page));
    }

    public Pagination<UserWorksComment> queryByInspiration(String title, Sorting[] sorts, Page page) {

        return Pagination.create(page,
            dao.countByInspiration(title),
            () -> dao.queryByInspiration(title, Sortings.builder(sorts).toSql(), page));
    }
}